﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Gamev1;
using Microsoft.Xna.Framework;

namespace Testen
{
    [TestClass]
    public class UnitTest1
    {
        public Character character;
        public Item item;
        public Weapon weapon;
        public Platform platform;
        public Zombie zombie;
        public Level level;
        public Bullet bullet;

        [TestInitialize]
        public void setup()
        {
            character = new Character();
            character.Position = new Vector2(200, 200);
            character.Velocity = Vector2.Zero;
            item = new Item();
            weapon = new Weapon();
            platform = new Platform();
            zombie = new Zombie();
            level = new Level();
            bullet = new Bullet(weapon);
        }

        private void updateCharacter(Character character)
        {
            character.Velocity += character.Acceleration;
            character.Position += character.Velocity;
            character.checkBounds();
        }

        private void updateZombie(Zombie zombie)
        {
            zombie.Position += zombie.Velocity;
        }

        private void updatePlatform(Platform platform)
        {
            platform.Position += platform.Velocity;
        }

        public void updateBullet(Bullet bullet)
        {
            bullet.Position += bullet.Velocity;
        }

        private void moveDown(Character character)
        {
            character.Velocity = new Vector2(character.Velocity.X, character.speed);
        }

        //1
        [TestMethod]
        public void TestApplyGravity()
        {
            float gravity = 5f;
            character.applyGravity(gravity);
            updateCharacter(character);
            gravity = 3f;
            character.applyGravity(gravity);
            updateCharacter(character);
            Vector2 actualVelocity = character.Velocity;
            Vector2 expectedVelocity = new Vector2(0, 8);
            Assert.AreEqual(expectedVelocity, actualVelocity);
        }

        //2
        [TestMethod]
        public void TestCheckHealth()
        {
            Enemy enemy = new Zombie();
            enemy.hit(character);
            enemy.hit(character);
            int actual = character.Health;
            int expected = 234;
            Assert.AreEqual(expected, actual);
        }

        //3
        [TestMethod]
        public void TestJump()
        {
            character.jump();
            updateCharacter(character);
            Vector2 actual = character.Position;
            Vector2 expected = new Vector2(200, 184);
            Assert.AreEqual(expected, actual);
        }

        //4
        [TestMethod]
        public void TestWalkLeft()
        {
            character.moveLeft();
            updateCharacter(character);
            Vector2 actual = character.Position;
            Vector2 expected = new Vector2(195, 200);
            Assert.AreEqual(expected, actual);
        }

        //5
        [TestMethod]
        public void TestWalkRight()
        {
            character.moveRight();
            updateCharacter(character);
            character.moveLeft();
            updateCharacter(character);
            character.moveRight();
            updateCharacter(character);
            character.moveRight();
            updateCharacter(character);
            Vector2 actual = character.Position;
            Vector2 expected = new Vector2(210, 200);
            Assert.AreEqual(expected, actual);
        }

        //6
        [TestMethod]
        public void testHealthItem()
        {
            item.bonusType = Item.Bonus.Health;
            character.Health = 100;
            item.collisionWith(character);
            int actual = character.Health;
            int expected = 125;
            Assert.AreEqual(expected, actual);
        }

        //7
        [TestMethod]
        public void testJumpItem()
        {
            item.bonusType = Item.Bonus.Jump;
            item.collisionWith(character);
            character.jump();
            updateCharacter(character);
            Vector2 actualPosition = character.Position;
            Vector2 expectedPosition = new Vector2(200, 179);
            bool actualHasBonus = character.hasBonus;
            bool expectedHasBonus = true;

            Assert.AreEqual(expectedPosition, actualPosition);
            Assert.AreEqual(expectedHasBonus, actualHasBonus);
        }

        //8
        [TestMethod]
        public void testTimeItem()
        {
            item.bonusType = Item.Bonus.Time;
            item.collisionWith(character);
            float actual = character.CurrentTime;
            float expected = 25;
            Assert.AreEqual(expected, actual);
        }

        //9
        [TestMethod]
        public void testGameOverOverTimeLimit()
        {
            Level level = new Level();
            level.character = character;
            character.TimeLimit = 90;
            character.CurrentTime = 100;
            level.checkGameOver();
            bool actual = level.isGameOver;
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //10
        [TestMethod]
        public void testGameOverCharacterDead()
        {
            Level level = new Level();
            level.character = character;
            character.Health = -1;
            level.checkGameOver();
            bool actual = level.isGameOver;
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //11
        [TestMethod]
        public void testPortalCollision()
        {
            Portal portal_1 = new Portal();
            Portal portal_2 = new Portal();
            Key key = new Key();

            character.Position = Vector2.Zero;
            key.collisionWith(character);


            bool actualHasKey = character.hasKey;
            bool expectedHasKey = true;
            Assert.AreEqual(expectedHasKey, actualHasKey);

            portal_1.Position = Vector2.Zero;
            portal_2.Position = new Vector2(100, 100);
            portal_1.portalPositions = new List<Vector2>();
            portal_1.portalPositions.Add(portal_2.Position);
            portal_1.collisionWith(character);

            Vector2 actualPosition = character.Position;
            Vector2 expectedPosition = portal_2.Position;
            Assert.AreEqual(expectedPosition, actualPosition);

            actualHasKey = character.hasKey;
            expectedHasKey = false;
            Assert.AreEqual(expectedHasKey, actualHasKey);
        }

        //12
        [TestMethod]
        public void testApplyBonus()
        {
            character.hasBonus = false;
            character.CurrentTime = 30;
            character.Health = 100;
            character.Position = Vector2.Zero;

            item.bonusType = Item.Bonus.Health;
            item.collisionWith(character);
            bool actualHasBonus = character.hasBonus;
            bool expectedHasBonus = false;
            int actualHealth = character.Health;
            int expectedHealth = 125;
            Assert.AreEqual(expectedHealth, actualHealth);
            Assert.AreEqual(expectedHasBonus, actualHasBonus);

            item.bonusType = Item.Bonus.Time;
            item.collisionWith(character);
            float actualTime = character.CurrentTime;
            float expectedTime = 55;
            actualHasBonus = character.hasBonus;
            expectedHasBonus = false;
            Assert.AreEqual(expectedTime, actualTime);
            Assert.AreEqual(expectedHasBonus, actualHasBonus);

            item.bonusType = Item.Bonus.Jump;
            item.collisionWith(character);
            float actualJumpHeight = character.JumpHeight;
            float expectedJumpHeight = -21f;
            actualHasBonus = character.hasBonus;
            expectedHasBonus = true;
            Assert.AreEqual(expectedJumpHeight, actualJumpHeight);
            Assert.AreEqual(expectedHasBonus, actualHasBonus);
        }


        //13
        [TestMethod]
        public void testCollisionWeapon()
        {
            weapon.collisionWith(character);

            Weapon actual = character.weapon;
            Weapon expected = weapon;
            Assert.AreEqual(weapon, actual);
        }

        //14
        [TestMethod]
        public void TestCheckBounds()
        {
            character.moveLeft();
            updateCharacter(character);
            character.moveLeft();
            updateCharacter(character);
            Vector2 actual = character.Position;
            Vector2 expected = new Vector2(190, 200);
            Assert.AreEqual(expected, actual);
        }

        //15
        [TestMethod]
        public void testCheckWeaponPosition()
        {
            weapon.character = character;
            int left = 0;
            int right = 1;
            character.CurrentDirection = left;
            weapon.checkDirection();
            weapon.checkPosition();
            Vector2 actualLeft = weapon.Position;
            Vector2 expectedLeft = new Vector2(99, 250);
            Assert.AreEqual(expectedLeft, actualLeft);

            character.CurrentDirection = right;
            weapon.checkDirection();
            weapon.checkPosition();
            Vector2 actualRight = weapon.Position;
            Vector2 expectedRight = new Vector2(301, 250);
            Assert.AreEqual(expectedRight, actualRight);
        }

        //16
        [TestMethod]
        public void testCheckWeaponDirection()
        {
            weapon.character = character;
            int left = 0;
            int right = 1;
            character.CurrentDirection = left;
            weapon.checkDirection();
            character.CurrentDirection = right;
            weapon.checkDirection();
            int actualDirection = weapon.direction;
            int expectedDirection = right;
            Assert.AreEqual(expectedDirection, actualDirection);

            character.CurrentDirection = right;
            weapon.checkDirection();
            character.CurrentDirection = left;
            weapon.checkDirection();
            actualDirection = weapon.direction;
            expectedDirection = left;
            Assert.AreEqual(expectedDirection, actualDirection);
        }

        //17
        [TestMethod]
        public void testCharacterPlatformCollision()
        {
            platform.Position = new Vector2(200, 150);
            bool actual = platform.isCollidingWith(character);
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //18
        [TestMethod]
        public void testPlatformTopCollision()
        {
            platform.Position = new Vector2(200, 201);
            platform.initializeRectangles();
            platform.collisionTop(character);
            bool actual = platform.isColliding(character, platform.top);
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //19
        [TestMethod]
        public void testPlatformBottomCollision()
        {
            platform.Position = new Vector2(200, 189);
            platform.initializeRectangles();
            platform.collisionBottom(character);
            bool actual = platform.isColliding(character, platform.bottom);
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //20
        [TestMethod]
        public void testPlatformLeftCollision()
        {
            platform.Position = new Vector2(210, 200);
            platform.initializeRectangles();
            platform.collisionLeft(character);
            bool actual = platform.isColliding(character, platform.left);
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //21
        [TestMethod]
        public void testPlatformRightCollision()
        {
            platform.Position = new Vector2(190, 200);
            platform.initializeRectangles();
            platform.collisionRight(character);
            bool actual = platform.isColliding(character, platform.right);
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //22
        [TestMethod]
        public void testPlatformMoveLeft()
        {
            platform.Position = new Vector2(100, 100);
            platform.platformType = Platform.TypePlatform.Movable;
            platform.movesVertical = false;
            platform.moveLeft();
            updatePlatform(platform);
            platform.moveLeft();
            updatePlatform(platform);
            Vector2 actual = platform.Position;
            Vector2 expected = new Vector2(98, 100);
            Assert.AreEqual(expected, actual);
        }

        //23
        [TestMethod]
        public void testPlatformMoveRight()
        {
            platform.Position = new Vector2(100, 100);
            platform.platformType = Platform.TypePlatform.Movable;
            platform.moveRight();
            updatePlatform(platform);
            platform.moveRight();
            updatePlatform(platform);
            Vector2 actual = platform.Position;
            Vector2 expected = new Vector2(102, 100);
            Assert.AreEqual(expected, actual);
        }

        //24
        [TestMethod]
        public void testPlatformMoveUp()
        {
            platform.Position = new Vector2(100, 100);
            platform.platformType = Platform.TypePlatform.Movable;
            platform.moveUp();
            updatePlatform(platform);
            platform.moveUp();
            updatePlatform(platform);
            Vector2 actual = platform.Position;
            Vector2 expected = new Vector2(100, 98);
            Assert.AreEqual(expected, actual);
        }

        //25
        [TestMethod]
        public void testPlatformMoveDown()
        {
            platform.Position = new Vector2(100, 100);
            platform.platformType = Platform.TypePlatform.Movable;
            platform.moveDown();
            updatePlatform(platform);
            platform.moveDown();
            updatePlatform(platform);
            Vector2 actual = platform.Position;
            Vector2 expected = new Vector2(100, 102);
            Assert.AreEqual(expected, actual);
        }

        //26
        [TestMethod]
        public void testMovingPlatformHasReachedHorizontalEnd()
        {
            platform.startPosition = new Vector2(100, 100);
            platform.platformType = Platform.TypePlatform.Movable;
            platform.movingLeft = true;
            platform.Position = new Vector2(1, 100);
            platform.moveLeft();
            updatePlatform(platform);
            platform.moveLeft();
            updatePlatform(platform);
            bool actual = platform.hasReachedHorizontalEnd();
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //27
        [TestMethod]
        public void testMovingPlatformHasReachedVerticalEnd()
        {
            platform.startPosition = new Vector2(100, 100);
            platform.platformType = Platform.TypePlatform.Movable;
            platform.movingLeft = false;
            platform.Position = new Vector2(199, 100);
            platform.moveRight();
            updatePlatform(platform);
            platform.moveRight();
            updatePlatform(platform);
            bool actual = platform.hasReachedHorizontalEnd();
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //28
        [TestMethod]
        public void testInsideCheckFieldofView()
        {
            level.allSprites = new List<Sprite>();
            level.character = character;
            level.allSprites.Add(character);
            level.allSprites.Add(zombie);
            character.Position = new Vector2(50, 50);
            zombie.Position = new Vector2(349, 50);
            zombie.direction = 0;
            level.checkEnemyFieldOfView();
            bool actual = zombie.canSeeCharacter;
            bool expected = true;
            Assert.AreEqual(expected, actual);
        }

        //29
        [TestMethod]
        public void testOutsideCheckFieldofView()
        {
            level.allSprites = new List<Sprite>();
            level.character = character;
            level.allSprites.Add(character);
            level.allSprites.Add(zombie);
            character.Position = new Vector2(50, 50);
            zombie.Position = new Vector2(350, 50);
            zombie.direction = 0;
            level.checkEnemyFieldOfView();
            bool actual = zombie.canSeeCharacter;
            bool expected = false;
            Assert.AreEqual(expected, actual);
        }

        //30
        [TestMethod]
        public void testcheckCharacterCollisions()
        {
            level.allSprites = new List<Sprite>();
            level.character = character;
            level.allSprites.Add(character);
            level.allSprites.Add(zombie);
            zombie.CanHit = true;
            character.Position = new Vector2(100, 100);
            zombie.Position = new Vector2(199, 199);
            level.checkCharacterCollisions();
            int actual = character.Health;
            int expected = 242;
            Assert.AreEqual(expected, actual);
        }

        //31
        [TestMethod]
        public void testcheckCharacterCollisions2()
        {
            level.allSprites = new List<Sprite>();
            level.character = character;
            level.allSprites.Add(character);
            level.allSprites.Add(zombie);
            zombie.CanHit = true;
            character.Position = new Vector2(100, 100);
            zombie.Position = new Vector2(201, 201);
            level.checkCharacterCollisions();
            int actual = character.Health;
            int expected = 250;
            Assert.AreEqual(expected, actual);
        }

        //32
        [TestMethod]
        public void testcheckBulletCollisions()
        {
            level.allSprites = new List<Sprite>();
            level.bulletSprites = new List<Bullet>();
            level.allSprites.Add(zombie);
            Bullet bullet = new Bullet(weapon);
            level.bulletSprites.Add(bullet);
            bullet.Position = Vector2.Zero;
            zombie.Position = Vector2.Zero;
            zombie.healthBar = new HealthBar(zombie.currentHealth);
            level.checkBulletCollisions();
            double actual = zombie.currentHealth;
            double expected = 87;
            Assert.AreEqual(expected, actual);
        }

        //33
        [TestMethod]
        public void testCalculateScore()
        {
            character.CurrentTime = 10;
            character.TimeLimit = 20;
            character.Health = 100;
            character.monstersKilled = 5;
            character.calculateScore();
            int actual = character.Score;
            int expected = 5650;
            Assert.AreEqual(expected, actual);
        }

        //34
        [TestMethod]
        public void testAtLeftEdge()
        {
            character.Position = new Vector2(11, 0);
            character.moveLeft();
            updateCharacter(character);
            character.moveLeft();
            updateCharacter(character);
            bool actual = character.atLeftEdge();
            bool expected = false;
            Assert.AreEqual(expected, actual);
            Vector2 actualPosition = character.Position;
            Vector2 expectedPosition = new Vector2(10, 0);
            Assert.AreEqual(expectedPosition, actualPosition);
        }

        //35
        [TestMethod]
        public void testAtRightEdge()
        {
            character.Position = new Vector2(1164, 0);
            character.moveRight();
            updateCharacter(character);
            character.moveRight();
            updateCharacter(character);
            bool actual = character.atRightEdge();
            bool expected = false;
            Assert.AreEqual(expected, actual);
            Vector2 actualPosition = character.Position;
            Vector2 expectedPosition = new Vector2(1170, 0);
            Assert.AreEqual(expectedPosition, actualPosition);
        }

        //36
        [TestMethod]
        public void testAtBottomEdge()
        {
            character.Position = new Vector2(200, 469);
            moveDown(character);
            updateCharacter(character);
            moveDown(character);
            updateCharacter(character);
            bool actual = character.atBottomEdge();
            bool expected = false;
            Assert.AreEqual(expected, actual);
            Vector2 actualPosition = character.Position;
            Vector2 expectedPosition = new Vector2(200, 470);
            Assert.AreEqual(expectedPosition, actualPosition);
        }

        //37
        [TestMethod]
        public void testCalculateHealthEnemy()
        {
            zombie.maxHealth = 200;
            double actual = zombie.calculateHealth(25);
            double expected = 50;
            Assert.AreEqual(expected, actual);
        }

        //38
        [TestMethod]
        public void testChase()
        {
            int left = 0;
            zombie.direction = left;
            zombie.moveLeft();
            updateZombie(zombie);
            zombie.chase(0.9f);
            updateZombie(zombie);
            Vector2 actual = zombie.Velocity;
            Vector2 expected = new Vector2(-0.9f, 0);
            Assert.AreEqual(expected, actual);
        }

        //39
        [TestMethod]
        public void testEnemyMoveLeft()
        {
            zombie.Position = new Vector2(200, 200);
            zombie.moveLeft();
            updateZombie(zombie);
            zombie.moveLeft();
            updateZombie(zombie);
            Vector2 actualVelocity = zombie.Velocity;
            Vector2 expectedVelocity = new Vector2(-0.8f, 0);
            Assert.AreEqual(expectedVelocity, actualVelocity);

            Vector2 actualPosition = zombie.Position;
            Vector2 expectedPosition = new Vector2(198.4f, 200);
            Assert.AreEqual(expectedPosition, actualPosition);
        }

        //40
        [TestMethod]
        public void testEnemyMoveRight()
        {
            zombie.Position = new Vector2(200, 200);
            zombie.moveRight();
            updateZombie(zombie);
            zombie.moveRight();
            updateZombie(zombie);
            Vector2 actualVelocity = zombie.Velocity;
            Vector2 expectedVelocity = new Vector2(0.8f, 0);
            Assert.AreEqual(expectedVelocity, actualVelocity);

            Vector2 actualPosition = zombie.Position;
            Vector2 expectedPosition = new Vector2(201.6f, 200);
            Assert.AreEqual(expectedPosition, actualPosition);
        }

        //41
        [TestMethod]
        public void testEnemyMoveLeft2()
        {
            zombie.Position = new Vector2(200, 200);
            float speed = 3.5f;
            zombie.moveLeft(speed);
            updateZombie(zombie);
            zombie.moveLeft(speed);
            updateZombie(zombie);
            Vector2 actualVelocity = zombie.Velocity;
            Vector2 expectedVelocity = new Vector2(-3.5f, 0);
            Assert.AreEqual(expectedVelocity, actualVelocity);

            Vector2 actualPosition = zombie.Position;
            Vector2 expectedPosition = new Vector2(193, 200);
            Assert.AreEqual(expectedPosition, actualPosition);
        }

        //42
        [TestMethod]
        public void testEnemyMoveRight2()
        {
            zombie.Position = new Vector2(200, 200);
            float speed = 4.5f;
            zombie.moveRight(speed);
            updateZombie(zombie);
            zombie.moveRight(speed);
            updateZombie(zombie);
            Vector2 actualVelocity = zombie.Velocity;
            Vector2 expectedVelocity = new Vector2(4.5f, 0);
            Assert.AreEqual(expectedVelocity, actualVelocity);

            Vector2 actualPosition = zombie.Position;
            Vector2 expectedPosition = new Vector2(209, 200);
            Assert.AreEqual(expectedPosition, actualPosition);
        }

        //43
        [TestMethod]
        public void testEnemyHit()
        {
            zombie.hit(character);
            zombie.hit(character);
            zombie.hit(character);
            int actual = character.Health;
            int expected = 226;
            Assert.AreEqual(expected, actual);
        }

        //44
        [TestMethod]
        public void testEnemyCheckAlive()
        {
            zombie.currentHealth = 100;
            zombie.checkAlive();
            bool actualCanBeRemoved = zombie.canBeRemoved;
            bool expectedCanBeRemoved = false;
            Assert.AreEqual(expectedCanBeRemoved, actualCanBeRemoved);

            zombie.currentHealth = -1;
            zombie.checkAlive();
            actualCanBeRemoved = zombie.canBeRemoved;
            expectedCanBeRemoved = true;
            Assert.AreEqual(expectedCanBeRemoved, actualCanBeRemoved);
        }

        //45    in enemy klasse item texture in commentaar zetten!
        [TestMethod]
        public void testEnemyDropsKey()
        {
            zombie.canDropKey = true;
            Item item = zombie.dropItem(null);
            Item item2 = item;

            Item actual = item;
            Item expected = item2;

            Assert.AreEqual(expected, actual);
        }

        //46 
        [TestMethod]
        public void testHealthbar()
        {
            zombie.healthBar = new HealthBar(zombie.maxHealth);
            Bullet bullet = new Bullet(weapon);
            zombie.healthBar.rectangle = new Rectangle(0, 0, (int)zombie.healthBar.health, 20);
            zombie.healthBar.Hit(bullet.power);

            int actual = zombie.healthBar.rectangle.Width;
            int expected = 87;
            Assert.AreEqual(expected, actual);
        }

        //47
        [TestMethod]
        public void testBulletPostion()
        {
            level.bulletSprites = new List<Bullet>();
            Bullet bullet = new Bullet(weapon);
            level.bulletSprites.Add(bullet);
            weapon.Position = new Vector2(200,200);
            bullet.direction = 0;
            bullet.checkPosition();
            bullet.move();
            updateBullet(bullet);
            bullet.move();
            updateBullet(bullet);
            Vector2 actual = bullet.Position;
            Vector2 expected = new Vector2(170, 200);
            Assert.AreEqual(expected, actual);
        }

        //48
        [TestMethod]
        public void testBossShoot()
        {
            Button button = new Button();
            button.color.A = 255;
            button.changeTransparency();
            button.changeTransparency();
            int actual = button.color.A;
            int expected = 249;
            Assert.AreEqual(expected, actual);

            button.color.A = 0;
            button.changeTransparency();
            button.changeTransparency();
            int actual2 = button.color.A;
            int expected2 = 6;
            Assert.AreEqual(expected2, actual2);
        }

        //49
        [TestMethod]
        public void testMoveCamera()
        {
            Camera camera = new Camera();
            character.Position = new Vector2(200, 500);
            camera.checkBounds(character);
            Vector2 actual = camera.Center;
            Vector2 expected = new Vector2(0, 120); //(500 + 100 / 2) - (600 / 2) - 130 = 550 - 300 - 130
            Assert.AreEqual(expected, actual);
        }

        //50
        [TestMethod]
        public void testCheckScaling()
        {
            Portal portal = new Portal();
            portal.adjustScaling();
            portal.adjustScaling();
            portal.adjustScaling();
            float actual = portal.scale;
            float expected = 0.985f;
            Assert.AreEqual(expected, actual);
        }
    }
}
